package registry

import (
	"github.com/samuel/go-zookeeper/zk"
	"log"
	"time"
)

type registry interface {
	Discovery(host, parent string) (chan []string, chan error)
	Register(host, parent, child string, data []byte) (err error)
}

type ZooKeeperRegistry struct {
	Host []string
}

//Register 注册节点，向目标主机的目标路径注册节点
func (z *ZooKeeperRegistry) Register(parent, child string, data []byte) (err error) {

	conn, _, err := zk.Connect(z.Host, 5*time.Second)
	// 1. 父节点不存在则新建
	ex, _, _ := conn.Exists(parent)
	if !ex {
		_, err = conn.Create(child, nil, 0, zk.WorldACL(zk.PermAll))
		if err != nil {
			log.Fatalf("create father node failed: %v", err)
			return
		}
	}

	child = parent + "/" + child
	// 2.1 子节点是否已挂载, 没挂则挂
	if ex, _, _ := conn.Exists(child); !ex {
		_, err = conn.Create(child, nil, zk.FlagEphemeral, zk.WorldACL(zk.PermAll))
		if err != nil {
			log.Fatalf("create child node failed: %v", err)
			return
		}
	}
	return
}

//Discovery 监听目标节点,放回两个channel，一个是变化以后的子节点快照，一个是错误信息
func (z *ZooKeeperRegistry) Discovery(parent string) (chan []string, chan error) {

	snapshots := make(chan []string) // 变动后的挂载目标列表
	errors := make(chan error)       // 变动错误信息
	conn, _, err := zk.Connect(z.Host, 5*time.Second)
	if err != nil {
		errors <- err
	}
	go func() {
		for {
			snapshot, _, events, err := conn.ChildrenW(parent)
			if err != nil {
				errors <- err
			}
			snapshots <- snapshot
			// 阻塞直到出现事件消息
			select {
			case evt := <-events:
				if evt.Err != nil {
					errors <- evt.Err
				}
				log.Printf("ChildrenW Event Path:%v, Type:%v\n", evt.Path, evt.Type)
			}
		}
	}()
	return snapshots, errors
}
